package ast


type MaybeExpr interface { impl(MaybeExpr) }
func (Expr) impl(MaybeExpr)  {}
type Expr struct {
	Node                       `part:"expr"`
	Casts     [] Cast          `list:"cast*"`
	Term      VariousTerm      `part:"term"`
	Pipeline  [] VariousPipe   `list:"pipe*"`
}

type Cast struct {
	Node           `part:"pipe_cast"`
	Target  Type   `part:"type"`
}

type VariousTerm struct {
	Node         `part:"term"`
	Term  Term   `use:"first"`
}
type Term interface { impl(Term) }

type VariousPipe struct {
	Node         `part:"pipe"`
	Pipe  Pipe   `use:"first"`
}
type Pipe interface { impl(Pipe) }


func (PipeCast) impl(Pipe) {}
type PipeCast struct {
	Node         `part:"pipe_cast"`
	Cast  Cast   `part:"cast"`
}

func (VariousPipeCall) impl(Pipe) {}
type VariousPipeCall struct {
	Node                 `part:"pipe_call"`
	PipeCall  PipeCall   `use:"first"`
}
type PipeCall interface { impl(PipeCall) }
func (CallOrdered) impl(PipeCall) {}
type CallOrdered struct {
	Node                 `part:"call_ordered"`
	Arguments  [] Expr   `list:"expr*,"`
}
func (CallUnordered) impl(PipeCall) {}
type CallUnordered struct {
	Node                           `part:"call_unordered"`
	Mappings  [] ArgumentMapping   `list:"arg_mapping*,"`
}
type ArgumentMapping struct {
	Node                `part:"arg_mapping"`
	Name   Identifier   `part:"name"`
	Value  MaybeExpr    `part_opt:"arg_mapping_to.expr"`
}

func (PipeUfcs) impl(Pipe) {}
type PipeUfcs struct {
	Node                        `part:"pipe_ufcs"`
	Callee    Ref               `part:"ref"`
	PipeCall  VariousPipeCall   `part:"pipe_call"`
}

func (PipeGet) impl(Pipe) {}
type PipeGet struct {
	Node               `part:"pipe_get"`
	Key   Identifier   `part:"name"`
}

func (PipeInterior) impl(Pipe) {}
type PipeInterior struct {
	Node               `part:"pipe_interior"`
	RefBase  RefBase   `part:"ref_base"`
}


func (InfixTerm) impl(Term) {}
type InfixTerm struct {
	Node             `part:"infix_term"`
	Operator  Ref    `part:"operator.ref"`
	Left      Expr   `part:"infix_left.expr"`
	Right     Expr   `part:"infix_right.expr"`
}

func (Lambda) impl(Term) {}
type Lambda struct {
	Node                           `part:"lambda"`
	InputNames   [] Identifier     `list:"input_names.name+,"`
	OutputExpr   Expr              `part:"expr"`
	SelfRefName  MaybeIdentifier   `part_opt:"rec.name"`
}

func (Block) impl(Term) {}
func (Block) implBody() {}
func (Block) implStringPart() {}
type Block struct {
	Node                          `part:"block"`
	Bindings  [] VariousBinding   `list:"binding*"`
	Return    Expr                `part:"expr"`
}
type VariousBinding struct {
	Node               `part:"binding"`
	Binding  Binding   `use:"first"`
}
type Binding interface { impl(Binding) }
func (BindingPlain) impl(Binding) {}
type BindingPlain struct {
	Node                      `part:"binding_plain"`
	Pattern  VariousPattern   `part:"pattern"`
	Value    Expr             `part:"expr"`
}
func (BindingCps) impl(Binding) {}
type BindingCps struct {
	Node                    `part:"binding_cps"`
	Callee   Ref            `part:"ref"`
	Pattern  MaybePattern   `part_opt:"cps_binding.pattern"`
	Value    Expr           `part:"expr"`
}

func (When) impl(Term) {}
type When struct {
	Node                   `part:"when"`
	Arguments  [] Expr     `list:"expr+,"`
	Branches   [] Branch   `list:"branch+,"`
}
type Branch struct {
	Node                           `part:"branch"`
	Patterns    [] BranchPattern   `list:"branch_pattern+_bar"`
	InputNames  [] Identifier      `list:"input_names.name+,"`
	OutputExpr  Expr               `part:"expr"`
}
type BranchPattern struct {
	Node                    `part:"branch_pattern"`
	Pattern  MaybePattern   `part_opt:"pattern"`
}

func (If) impl(Term) {}
type If struct {
	Node             `part:"if"`
	Cond   Expr      `part:"cond.expr"`
	Yes    Block     `part:"if_yes.block"`
	No     Block     `part:"if_no.block"`
	ElIfs  [] ElIf   `list:"elif*"`
}
type ElIf struct {
	Node         `part:"elif"`
	Cond  Expr   `part:"cond.expr"`
	Yes   Expr   `part:"block"`
}

func (RefTerm) impl(Term) {}
type RefTerm struct {
	Node        `part:"ref_term"`
	New  bool   `option:"new.New"`
	Ref  Ref    `part:"ref"`
}


type MaybePattern interface { impl(MaybePattern) }
func (VariousPattern) impl(MaybePattern) {}
type VariousPattern struct {
	Node               `part:"pattern"`
	Pattern  Pattern   `use:"first"`
}
type Pattern interface { impl(Pattern) }

func (PatternSingle) impl(Pattern) {}
type PatternSingle struct {
	Node                `part:"pattern_single"`
	Name   Identifier   `part:"name"`
}

func (PatternMultiple) impl(Pattern) {}
type PatternMultiple struct {
	Node                   `part:"pattern_multiple"`
	Names  [] Identifier   `list:"name+,"`
}


